package com.nowcoder.community.quartz;

import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.service.DiscussPostService;
import com.nowcoder.community.service.ElasticseachService;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.RedisKeyUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.RedisTemplate;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author TwfPlayer
 * @date 2023/8/21 17:34
 * @description: 帖子热度更新任务
 */

public class PostScoreRefreshJob implements Job, CommunityConstant {

    private static final Logger logger = LoggerFactory.getLogger(PostScoreRefreshJob.class);

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private DiscussPostService discussPostService;

    @Autowired
    private LikeService likeService;

    @Autowired
    private ElasticseachService elasticseachService;

    //热度初始时间
    private static final Date eposh;

    static {
        try {
            eposh = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2023-08-01 00:00:00");
        } catch (ParseException e) {
            throw new RuntimeException("初始化热度时间失败!", e);
        }
    }

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String redisKey = RedisKeyUtil.getHeatKey();
        BoundSetOperations operations = redisTemplate.boundSetOps(redisKey);

        if (operations.size() == 0) {
            logger.info("任务取消:[没有需要刷新的贴子!]");
            return;
        }

        logger.info("任务开始:[刷新帖子热度]:" + operations.size());
        //此处更新时,若有人不断对某一帖子点赞或评论操作,该任务可能不会停止
        while (operations.size() > 0) {
            this.refresh((Integer) operations.pop());
        }
        logger.info("任务结束:[热度刷新完毕]!");
    }

    private void refresh(int postId) {
        DiscussPost post = discussPostService.findDiscussPostById(postId);
        //修改了xml,排除了帖子被拉黑的情况
        if (post == null) {
            logger.error("该贴不存在: id = " + postId);
            return;
        }
        //是否加精
        boolean wonderful = post.getStatus() == POST_WONDERFUL;
        //评论数量
        int commentCount = post.getCommentCount();
        //点赞数
        long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, postId);

        //权重
        double w = (wonderful ? 75 : 0) + commentCount * 10 + likeCount * 2;
        //分数=权重+间隔天数
        double score = Math.log10(Math.max(w, 1))
                + (post.getCreateTime().getTime() - eposh.getTime()) / (1000 * 3600 * 24);
        //更新分数
        discussPostService.setScore(postId, score);
        //同步搜索数据
        post.setScore(score);
        elasticseachService.saveDiscussPost(post);
    }

}
